package com.rockcent.service.impl;

import com.rockcent.common.common.BusinessException;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.ExcelCreateUtils;
import com.rockcent.helper.IntegrationCashCouponHelper;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.CashCouponStatus;
import com.rockcent.mall.lib.domain.enumclass.CustomerCouponWalletStatus;
import com.rockcent.mall.lib.domain.enumclass.MallOrderStatus;
import com.rockcent.mall.lib.domain.enumclass.MerchantCouponStatus;
import com.rockcent.mall.lib.dto.*;
import com.rockcent.mall.lib.repository.*;
import com.rockcent.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by zhangjh on 2016/12/19.
 */
@Service
public class MallCashCouponSrvImpl implements MallCashCouponSrv {

    private final Logger log = LoggerFactory.getLogger(MallCashCouponSrvImpl.class);

    @Autowired
    private MallCashCouponRepository mallCashCouponRepository;

    @Autowired
    private MerchantCouponSrv merchantCouponSrv;

    @Autowired
    private IntegrationCashCouponWalletSrv integrationCashCouponWalletSrv;

    @Autowired
    private IntegrationCouponWalletSrv integrationCouponWalletSrv;

    @Autowired
    private MallFundRepository mallFundRepository;

    @Autowired
    private MallCashCouponFlowSrv mallCashCouponFlowSrv;

    @Autowired
    private IntegrationCashCouponWalletRepository integrationCashCouponWalletRepository;

    @Autowired
    private IntegrationCouponWalletRepository integrationCouponWalletRepository;

    @Autowired
    private CustomerCouponWalletRepository customerCouponWalletRepository;

    /**
     * @param vo
     * @param mallId
     * @return
     */
    @Override
    public MallCashCoupon save(MallCashCouponDto vo, Long mallId) {
        String status = vo.getStatus();
        MallCashCoupon mallCashCoupon = IntegrationCashCouponHelper.SINGLETNONE.chgDtoToDomain(vo);
        mallCashCoupon.setMallId(mallId);
        if (CashCouponStatus.valueOf(status) == CashCouponStatus.WAIT_ISSUE) {
            mallCashCoupon.setStatus(CashCouponStatus.WAIT_ISSUE);
        } else if (CashCouponStatus.valueOf(status) == CashCouponStatus.ISSUED) {
            mallCashCoupon.setStatus(CashCouponStatus.ISSUED);
        }
        mallCashCoupon = mallCashCouponRepository.save(mallCashCoupon);//现金券基础信息
        if (CashCouponStatus.valueOf(status) == CashCouponStatus.ISSUED) {

            Long integrationChannelId = 1l;
            mallCashCoupon.setIntegrationChannelId(integrationChannelId);
            save(mallCashCoupon, mallId);

            integrationCashCouponWalletSrv.save(mallCashCoupon);

            //平台的现金券金额增加
            MallFund mallFund = mallFundRepository.findByMallId(mallId);
            mallFund = mallFundRepository.findOne(mallFund.getId());
            BigDecimal cashAmount = mallCashCoupon.getFaceValue().multiply(new BigDecimal(mallCashCoupon.getQuantity()));
            BigDecimal availableCashAmount = mallFund.getAvailableCashAmount();
            availableCashAmount = availableCashAmount == null ? BigDecimal.valueOf(0) : availableCashAmount;
            mallFund.setAvailableCashAmount(availableCashAmount.add(cashAmount));
            mallFundRepository.save(mallFund);

            mallCashCouponFlowSrv.income(mallId, mallCashCoupon.getId(), cashAmount);

        }


        //投送渠道


        return mallCashCoupon;

    }

    /**
     * @param id
     * @return
     */
    @Override
    public MallCashCoupon findOne(Long id) {
        MallCashCoupon mallCashCoupon = mallCashCouponRepository.findOne(id);
        return mallCashCoupon;
    }

    /**
     * 投放次号+1
     *
     * @param mallCashCoupon
     * @param mallId
     */
    @Override
    public void save(MallCashCoupon mallCashCoupon, Long mallId) {
        Long integrationChannelId = mallCashCoupon.getIntegrationChannelId();

        Long maxBatchPutNo = mallCashCouponRepository.queryMaxBatchPutNo(mallId, integrationChannelId);
        Long nexBatchPutNo = maxBatchPutNo + 1;

        mallCashCoupon.setBatchPutNo(nexBatchPutNo);
        mallCashCouponRepository.save(mallCashCoupon);//现金券基础信息
        integrationCashCouponWalletSrv.update(mallCashCoupon, mallId);

    }

    /**
     * @param mallCashCoupon
     * @param mallId
     */
    @Override
    public void stop(MallCashCoupon mallCashCoupon, Long mallId) {
//        mallCashCoupon = mallCashCouponRepository.findOne(mallCashCoupon.getId());
        mallCashCoupon.setStatus(CashCouponStatus.SOLDOUT);
        mallCashCouponRepository.save(mallCashCoupon);//现金券基础信息
        integrationCashCouponWalletSrv.stop(mallCashCoupon, mallId);

        Long counts = integrationCashCouponWalletSrv.countByExchangeNumAndCashCouponIdAndMallIdAndIsDelete(0l, mallCashCoupon.getId(), mallId, Whether.YES);
        //平台的现金券金额减少
        MallFund mallFund = mallFundRepository.findByMallId(mallId);
        mallFund = mallFundRepository.findOne(mallFund.getId());
        BigDecimal cashAmount = mallCashCoupon.getFaceValue().multiply(new BigDecimal(counts));
        BigDecimal availableCashAmount = mallFund.getAvailableCashAmount();
        availableCashAmount = availableCashAmount == null ? BigDecimal.valueOf(0) : availableCashAmount;
        mallFund.setAvailableCashAmount(availableCashAmount.subtract(cashAmount));
        mallFundRepository.save(mallFund);

        mallCashCouponFlowSrv.expend(mallId, mallCashCoupon.getId(), cashAmount);
    }

    /**
     * @param mallId
     * @param dto
     * @param pageResult
     * @return
     */
    @Override
    public PageResult<MallCashCouponDto> findIntegrationCashCouponPage(Long mallId, MallCashCouponDto dto, PageResult pageResult) {

        BigDecimal faceValue = dto.getFaceValue();
        String startTime = dto.getStartTime();
        if (StringUtils.isNotBlank(startTime)) {
            startTime = startTime + " 00:00:00";
        }

        String endTime = dto.getEndTime();
        if (StringUtils.isNotBlank(endTime)) {
            endTime = endTime + " 23:59:59";
        }
        Long channelId = dto.getIntegrationChannelId();
        String status = dto.getStatus();
        return mallCashCouponRepository.findIntegrationCashCouponPage(mallId, faceValue, startTime, endTime, channelId, status, pageResult);
    }

    /**
     * @param mallCashCoupon
     * @param mallId
     * @return
     */
    @Override
    public MallCashCoupon update(MallCashCoupon mallCashCoupon, Long mallId) {

        MallCashCoupon cashCoupon = mallCashCouponRepository.save(mallCashCoupon);
        if (mallCashCoupon.getStatus() == CashCouponStatus.ISSUED) {
//            integrationCashCouponWalletSrvImpl.save(mallCashCoupon);


            dist(mallCashCoupon, mallId);
        }
        return cashCoupon;
    }

    /**
     * @param mallCashCoupon
     * @param mallId
     */
    private void dist(MallCashCoupon mallCashCoupon, Long mallId) {
        Long integrationChannelId = 1l;
        mallCashCoupon.setIntegrationChannelId(integrationChannelId);
        save(mallCashCoupon, mallId);

        integrationCashCouponWalletSrv.save(mallCashCoupon);

        //平台的现金券金额增加
        MallFund mallFund = mallFundRepository.findByMallId(mallId);
        mallFund = mallFundRepository.findOne(mallFund.getId());
        BigDecimal cashAmount = mallCashCoupon.getFaceValue().multiply(new BigDecimal(mallCashCoupon.getQuantity()));
        BigDecimal availableCashAmount = mallFund.getAvailableCashAmount();
        availableCashAmount = availableCashAmount == null ? BigDecimal.valueOf(0) : availableCashAmount;
        mallFund.setAvailableCashAmount(availableCashAmount.add(cashAmount));
        mallFundRepository.save(mallFund);

        mallCashCouponFlowSrv.income(mallId, mallCashCoupon.getId(), cashAmount);
    }

    /**
     * @param vo
     */
    @Override
    public void delete(MallCashCoupon vo) {
        vo.setIsDelete(Whether.YES);
        mallCashCouponRepository.save(vo);
    }

    /**
     * @param reqDto
     * @param channelId
     * @return
     */
    @Override
    public List<IntegrationCouponRespDto> queryList(IntegrationCouponReqDto reqDto, String channelId) {
        String type = reqDto.getType();
        List<IntegrationCouponRespDto> respDtos = new ArrayList<>();
        if (StringUtils.isNotBlank(channelId)) {
            Long integrationChannelId = Long.parseLong(channelId);
            if ("coupon".equals(type)) {
                respDtos = merchantCouponSrv.findByIntegrationAndIntegrationChannelIdAndStatus(Whether.YES, integrationChannelId, MerchantCouponStatus.ISSUED);
                if (null != respDtos && !respDtos.isEmpty()) {
                    for (IntegrationCouponRespDto respDto : respDtos) {
                        List<IntegrationCouponDetailRespDto> detailRespDtos = integrationCouponWalletSrv.findByCounponId(respDto.getId());
                        Long counts = 0l;
                        if (null != detailRespDtos && !detailRespDtos.isEmpty()) {
                            respDto.setExchangeCodes(detailRespDtos);
                            counts = Long.valueOf(detailRespDtos.size());
                        }
                        respDto.setCounts(counts);
                    }
                }

            } else if ("cash".equals(type)) {
                respDtos = queryAllCashCoupon(channelId);
                for (IntegrationCouponRespDto respDto : respDtos) {
                    List<IntegrationCouponDetailRespDto> detailRespDtos = integrationCashCouponWalletSrv.findByCashCounponId(respDto.getId());
                    Long counts = 0l;
                    if (null != detailRespDtos && !detailRespDtos.isEmpty()) {
                        respDto.setExchangeCodes(detailRespDtos);
                        counts = Long.valueOf(detailRespDtos.size());
                    }
                    respDto.setCounts(counts);

                }
            } else {
                throw new BusinessException("卡券类型错误");
            }
        } else {
            throw new BusinessException("渠道信息不正确");
        }

        List<IntegrationCouponRespDto> result = respDtos.stream().filter(bean -> bean.getCounts() > 0l).collect(Collectors.toList());
        return result;
    }

    /**
     * @param channelId
     * @return
     */
    private List<IntegrationCouponRespDto> queryAllCashCoupon(String channelId) {

        return mallCashCouponRepository.queryAllCashCoupon(Long.valueOf(channelId));
    }

    /**
     * @param exchangeCode
     * @param channelId
     */
    @Override
    public void exchange(String exchangeCode, String channelId, IntegrationCouponReqDto dto) {
        Long integrationChannelId = Long.parseLong(channelId);
        Date now = new Date();
        String type = dto.getType();


        if ("cash".equals(type)) {

            IntegrationCashCouponWallet cashWallet = integrationCashCouponWalletSrv.findByExchangeCodeAndIntegrationChannelIdAndIsDeleteAndExchangeNum(exchangeCode, integrationChannelId, Whether.NO, 0l);

            if (null != cashWallet) {
                Whether whether = cashWallet.getIsDelete();
                if (whether == whether.YES) {
                    throw new BusinessException("该现金券不能在兑换");
                }
                cashWallet.setExchangeNum(1l);
                cashWallet.setExchangeDate(now);
                cashWallet.setOrderNo(dto.getOrderNo());
                integrationCashCouponWalletSrv.save(cashWallet);
            } else {
                throw new BusinessException("该现金券不存在或者已兑换，不能兑换或者重复兑换");
            }

        } else if ("coupon".equals(type)) {
            IntegrationCouponWallet couponWallet = integrationCouponWalletSrv.findByExchangeCodeAndIntegrationChannelIdAndIsDeleteAndExchangeNum(exchangeCode, integrationChannelId, Whether.NO, 0l);

            if (null != couponWallet) {
                Whether whether = couponWallet.getIsDelete();
                if (whether == whether.YES) {
                    throw new BusinessException("该抵扣券不能在兑换");
                }
                couponWallet.setExchangeNum(1l);
                couponWallet.setExchangeDate(now);
                couponWallet.setOrderNo(dto.getOrderNo());
                integrationCouponWalletSrv.save(couponWallet);
            } else {
                throw new BusinessException("该抵扣券不存在或者已兑换，不能兑换或者重复兑换");
            }
        } else {
            throw new BusinessException("卡券类型错误");
        }

    }


    /**
     * @param response
     * @param items
     * @param mallId
     * @throws IOException
     * @throws InvalidFormatException
     */
    @Override
    public void exchange(HttpServletResponse response, List<IntegrationChannelDto> items, Long mallId) throws IOException, InvalidFormatException {
//        Map<String, Object> data = new HashMap<>();
//        data.put("items", items);
        Date date = new Date();
        String dataName = "data";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String timeRam = sdf.format(date);
        ExcelCreateUtils.getInstance().create(items, dataName, timeRam + "-" + MallCashCouponSrvImpl.FILE_NAME_INTEGRATION, response, RESOURCE_PATH_INTEGRATION_CHANNEL);

    }

    /**
     * @param integrationChannelId
     * @return
     */
    @Override
    public Long queryTotalNumByChannelId(Long integrationChannelId) {
        return mallCashCouponRepository.queryTotalNum(integrationChannelId);
    }

    /**
     * @param mallOrder
     */
    @Override
    public BigDecimal refundIntegrationCoupon(MallOrder mallOrder) {
        return refundIntegrationCoupon(mallOrder, false);
    }

    /**
     * @param mallOrder
     * @param isNeedRefundMallFund
     */
    @Override
    public BigDecimal refundIntegrationCoupon(MallOrder mallOrder, boolean isNeedRefundMallFund) {
        Long integrationCashId = mallOrder.getIntegrationCashCouponId();
        Long integrationCouponId = mallOrder.getIntegrationCouponId();
        BigDecimal faceValue = null;
        if (null != integrationCashId) {
            log.info("======================>退积分现金券,integrationCashId:" + integrationCashId);
            IntegrationCashCouponWallet integrationCashCouponWallet = integrationCashCouponWalletRepository.findOne(integrationCashId);
            if (null != integrationCashCouponWallet) {
                faceValue = integrationCashCouponWallet.getFaceValue();//待取消订单的现金券
                integrationCashCouponWallet.setUseNum(0l);
                integrationCashCouponWallet.setUseDate(null);
                integrationCashCouponWalletRepository.save(integrationCashCouponWallet);

                MallOrderStatus status = mallOrder.getStatus();
                if (status == MallOrderStatus.PAYED || isNeedRefundMallFund) {
                    //平台冻结减，可用现金券加
                    MallFund mallFund = mallFundRepository.findOne(mallOrder.getMallFundId());
                    mallFund.setFrozen(mallFund.getFrozen().subtract(faceValue));
                    mallFund.setTotalAmount(mallFund.getTotalAmount().subtract(faceValue));
                    mallFund.setAvailableCashAmount(mallFund.getAvailableCashAmount().add(faceValue));
                    mallFundRepository.save(mallFund);
                }
            }


        }
        if (null != integrationCouponId) {
            log.info("======================>退积分优惠券,integrationCouponId:" + integrationCouponId);
            IntegrationCouponWallet integrationCouponWallet = integrationCouponWalletRepository.findOne(integrationCouponId);
            if (null != integrationCouponWallet) {
                integrationCouponWallet.setUseNum(0l);
                integrationCouponWallet.setUseDate(null);
                integrationCouponWalletRepository.save(integrationCouponWallet);

                CustomerCouponWallet customerCouponWallet = customerCouponWalletRepository.findByIntegrationCouponId(integrationCouponId);
                if (null != customerCouponWallet) {
                    log.info("======================>customerCouponWallet:" + customerCouponWallet);
                    customerCouponWallet.setStatus(CustomerCouponWalletStatus.TO_USE);
                    customerCouponWallet.setUseNum(0l);
                    customerCouponWalletRepository.save(customerCouponWallet);
                }

            }


        }
        return faceValue;
    }

    /**
     * 查询积分卡券状态
     *
     * @param exchangeCode 兑换码
     * @param dto          卡券信息
     * @param channelId    积分渠道
     * @return
     */
    @Override
    public IntegrationCouponDetailRespDto queryInfoByExchangeCodeAndType(String exchangeCode, IntegrationCouponReqDto dto, String channelId) {
        Long integrationChannelId = Long.parseLong(channelId);
        String type = dto.getType();
        IntegrationCouponDetailRespDto respDto = new IntegrationCouponDetailRespDto();
        if ("cash".equals(type)) {
            IntegrationCashCouponWallet wallet = integrationCashCouponWalletSrv.findByExchangeCodeAndIntegrationChannelIdAndIsDelete(exchangeCode, integrationChannelId, Whether.NO);
            if (null == wallet) {
                throw new BusinessException("该现金券不存在");
            }
            Long exchangeNum = wallet.getExchangeNum();
            if (1l == exchangeNum) {
                throw new BusinessException("该现金券已兑换");
            }
            respDto.setExchangeCode(exchangeCode);
            respDto.setFlagCode(wallet.getFlagCode());
        } else if ("coupon".equals(type)) {
            IntegrationCouponWallet wallet = integrationCouponWalletSrv.findByExchangeCodeAndIntegrationChannelIdAndIsDelete(exchangeCode, integrationChannelId, Whether.NO);
            if (null == wallet) {
                throw new BusinessException("该折扣券不存在");
            }
            Long exchangeNum = wallet.getExchangeNum();
            if (1l == exchangeNum) {
                throw new BusinessException("该折扣券已兑换");
            }
            respDto.setExchangeCode(exchangeCode);
            respDto.setFlagCode(wallet.getFlagCode());
        } else {
            throw new BusinessException("卡券类型错误");
        }
        return respDto;
    }

    @Override
    public IntegrationCouponRespDto exchange(BigDecimal faceVal, String channelId, IntegrationCouponReqDto dto) {
        String type = dto.getType();
        IntegrationCouponRespDto respDto = new IntegrationCouponRespDto();
        if (StringUtils.isNotBlank(channelId)) {
            Long integrationChannelId = Long.parseLong(channelId);
            if ("coupon".equals(type)) {
                respDto = merchantCouponSrv.findTop1ByIntegrationAndIntegrationChannelIdAndStatusAndFaceVal(Whether.NO, integrationChannelId, MerchantCouponStatus.ISSUED, faceVal);
                if (null != respDto) {
                    IntegrationCouponWallet wallet = integrationCouponWalletSrv.findTop1ByIdAndIntegrationChannelIdAndIsDeleteAndExchangeNum(respDto.getId(), integrationChannelId, Whether.NO, 0l);
                    if (null != wallet) {
                        respDto.setFlagCode(wallet.getFlagCode());
                        respDto.setExchangeCode(wallet.getExchangeCode());
                        wallet.setExchangeNum(1l);
                        wallet.setExchangeDate(new Date());
                        wallet.setOrderNo(dto.getOrderNo());
                        integrationCouponWalletSrv.save(wallet);

                    } else {
                        throw new BusinessException("没有指定面值的卡券");
                    }
                } else {
                    throw new BusinessException("没有指定面值的卡券");
                }
            } else if ("cash".equals(type)) {
                IntegrationCashCouponWallet wallet = integrationCashCouponWalletSrv.findTop1ByFaceValueAndIntegrationChannelIdAndIsDeleteAndExchangeNum(faceVal, integrationChannelId, Whether.NO, 0l);
                if (null != wallet) {
                    respDto.setFlagCode(wallet.getFlagCode());
                    respDto.setExchangeCode(wallet.getExchangeCode());
                    respDto.setFaceValue(wallet.getFaceValue());
                    wallet.setExchangeNum(1l);
                    wallet.setExchangeDate(new Date());
                    wallet.setOrderNo(dto.getOrderNo());
                    integrationCashCouponWalletRepository.save(wallet);
                } else {
                    throw new BusinessException("没有指定面值的现金券");
                }

            } else {
                throw new BusinessException("卡券类型错误");
            }
        } else {
            throw new BusinessException("渠道信息不正确");
        }

        return respDto;
    }


}
